package com.jl.obulibrary.operate;

import android.util.Log;

import com.jl.obulibrary.bean.CarAllBean;
import com.jl.obulibrary.bean.CarHCBean;
import com.jl.obulibrary.bean.CarKCBean;
import com.jl.obulibrary.bean.CardBean;
import com.jl.obulibrary.bean.GetSecureBean;
import com.jl.obulibrary.bean.ObuBean;
import com.jl.obulibrary.sdk.SDK_PSAM;
import com.jl.obulibrary.sdk.SDK_RSU;
import com.jl.obulibrary.servive.OperationByDSRC;
import com.jl.obulibrary.servive.OperationBySerialPort;
import com.jl.obulibrary.setting.OfflineSetting;
import com.jl.obulibrary.utils.HexUtil;
import com.jxhc.rsudriver.model.TransferChannel_res;

/**
 * 脱机操作  检测  激活  交易流程
 */
public class OfflineOperate {
    private String strResult = null;
    //    private static String strVst = null;
    private static String strGetSecure = null;
    private static String strGetRand = null;
    private static String strTransferChannel = null;
    private static String strTransferChannelPrivate = null;
    private static String strSetMMi = null;
    private static String strGetTollData = null;
    private static String strSetTollData = null;
    private static String strPsamRst = null;
    private static String strPsamCmd = null;
    private static String strGetSecureRand = null;
    private static int nLenVehiInfo = 0;

    private static String strMacId = null;
    private static String strLLC = "77";

    private static int nCardNoExist = 0;//卡片是否存在
    private static int nCardIsGx = 0;//卡片地区广西
    private static int nCardAlgId = 0;//卡片算法标识，0表示DES，4表示国密
    private static int nObuAlgId = 0;//OBU算法标识，0表示DES，4表示国密
    public static int nCardVersionType = 0;// ０表示旧版卡，１表示４X版本卡
    public static int nObuVersionType = 0;// OBU版本，0表示旧版本，1表示4X版本
    private static String strVst0015 = "";
    private static String strVst0002 = "";
    private static String strVstSystemFile = "";
    private static String strVstObuStatus = "";
    private static String strVstRandom = "";
    private static String strEsamSystemFile2 = "";// 系统信息27字节后面的信息
    private static String str0002 = "";//通过TransferChannel
    private static String str0019 = "";//通过TransferChannel
    private static String str0015 = "";//通过TransferChannel
    private static String str001B = "";//通过TransferChannel
    private static String strEsamVehicleFile = "";//车辆信息明文
    private static String strGetTollInfo = "";//过站信息
    private static String strTacInfo = "";//TAC信息
    private static String strAuthenticator = "";//鉴别码
    private static int nIsObuOneChip = 0;//1表示单片式
    private static String strExminObuMac = "";
    private static int nIsCheckEsamIccVersion = 0;//核对OBU和卡片版本，1表示核对，0表示不核对


    private static final byte MAC_CONTROL = 4;

    private static final byte ACTION_RQ = MAC_CONTROL + 3;
    private static final byte ACTION_RS = MAC_CONTROL + 4;

    private static final byte ACTION_TYPE = ACTION_RQ + 2;

    private static final byte DOWN_CONTAINER = ACTION_TYPE + 1;
    private static final byte UP_CONTAINER = ACTION_RS + 2;

    private static final byte DOWN_CONTAINER_G = ACTION_TYPE + 8;
    /******* DSRC_LINK ********************/
    private static final byte LINK_UP = (byte) 0x80;
    private static final byte LINK_DOWN = (byte) 0x40;
    /********* DSRC ACTION REQUEST/RESPONSE ****************************/
    private static final byte TYPE_BST = (byte) 0xC0;
    private static final byte TYPE_VST = (byte) 0xD0;
    private static final byte TYPE_EVENT = (byte) 0x60;

    private static final byte TYPE_ACTION_RQ = (byte) 0x05;
    private static final byte TYPE_ACTION_RQ1 = (byte) 0x00;
    private static final byte TYPE_ACTION_RS = (byte) 0x18;
    private static final byte TYPE_ACTION_RS1 = (byte) 0x10;
    /******** CONTAINER EVENT_REPORT ************************************/
    private static final byte C_GET_RQ = (byte) 0x14;
    private static final byte C_GET_RS = (byte) 0x15;
    private static final byte C_TRAN_RQ = (byte) 0x18;
    private static final byte C_TRAN_RS = (byte) 0x19;
    private static final byte C_SETM_RQ = (byte) 0x1A;
    private static final byte C_SETM_RS = (byte) 0x1B;
    private static final byte C_GETRNAD_RS = (byte) 0x1D;
    private static final byte C_GETTOLLDATA_RQ = (byte) 0x2A;
    private static final byte C_GETTOLLDATA_RS = (byte) 0x2B;
    private static final byte C_SETTOLLDATA_RQ = (byte) 0x2C;
    private static final byte C_SETTOLLDATA_RS = (byte) 0x2D;

    private static final byte R_BST = (byte) 0x01;
    private static final byte R_VST = (byte) 0x02;
    private static final byte R_GET_RQ = (byte) 0x03;
    private static final byte R_GET_RS = (byte) 0x04;
    private static final byte R_TRANS_RQ = (byte) 0x05;
    private static final byte R_TRANS_RS = (byte) 0x06;
    private static final byte R_SETM_RQ = (byte) 0x07;
    private static final byte R_SETM_RS = (byte) 0x08;
    private static final byte R_EVENT_REPORT = (byte) 0x09;
    private static final byte R_GETRAND_RS = (byte) 0x0A;
    private static final byte R_GETTOLLDATA_RQ = (byte) 0x0B;
    private static final byte R_GETTOLLDATA_RS = (byte) 0x0C;
    private static final byte R_SETTOLLDATA_RQ = (byte) 0x0D;
    private static final byte R_SETTOLLDATA_RS = (byte) 0x0E;

    private static final byte VST_OPTION_ETC = (byte) 0x01;
    private static final byte VST_OPTION_DID = (byte) 0x80;
    private static final byte VST_RESOLVE_START = (byte) 0x09;
    private static final byte VST_RESOLVE_START_OLD = (byte) 10;
    private static final byte CONTAINER_MF1_LEN = 52;
    private static final byte CONTAINER_RAND = 29; // Rand

    private static final byte CONTAINER_RAND_LEN = 8; // Random Length

    /*************** return ****************/
    private static final byte ERROR_NO_ETC_A = 19; //
    private static final byte ERROR_NOSYSFILE = 20; //
    private static final byte ERROR_LEN_ERROR = 21; //
    private static final byte ERROR_VST_L_MAC = 22; //
    private static final byte EFFOR_MF1 = 23; //
    private static final byte ERROR_VST_RAND = 40;
    private static final byte ERROR_CHANNEL_SW = 37;
    private static final byte ERROR_SW = 38;

    private static final byte LEN_SYS = 26;
    private static final byte VST_15_LEN = 43;


    public static byte VstResolve(String strVst, byte[] pVst, byte len) throws Exception {
        strMacId = strVst.substring(0, 8);

        byte offset = 9;
        byte flag;
        nCardVersionType = 0;
        nObuVersionType = 0;
        strVst0015 = "";
        strVst0002 = "";
        offset++;


        if ((pVst[offset] & 0x3F) != VST_OPTION_ETC)
            return ERROR_NO_ETC_A;
        if ((pVst[offset] & VST_OPTION_DID) == VST_OPTION_DID)
            offset++;// DID
        offset++;

        flag = pVst[offset];// ApplicationContextMark
        offset++;

        if ((flag & 0x20) == 0x20) {
            if ((pVst[offset] != 0x27) && (pVst[offset] != 0x20))//
                return ERROR_NOSYSFILE;
        }
        offset++;

        strVstSystemFile = strVst.substring(offset * 2, offset * 2 + LEN_SYS
                * 2);
        Log.e(TAG, "预读取OBU系统信息为:" + strVstSystemFile);


        int nObuVersion = Integer.parseInt(strVstSystemFile.substring(9 * 2, 10 * 2), 16);
        if ((nObuVersion & 0x40) == 0x40)
            nObuVersionType = 1;
        else
            nObuVersionType = 0;
        if ((nObuVersion & 0x50) == 0x50)
            nObuAlgId = 4;
        else
            nObuAlgId = 0;

        strVstRandom = "";
        offset += LEN_SYS;
        if ((flag & 0x80) == 0x80) {
            if (pVst[offset] != CONTAINER_RAND)
                return ERROR_VST_RAND;
            strVstRandom = strVst.substring((offset + 1) * 2, (offset + 1) * 2
                    + CONTAINER_RAND_LEN * 2);
            offset += (CONTAINER_RAND_LEN + 1);
        }

        if (offset > len)
            return ERROR_LEN_ERROR;
        strVstObuStatus = strVst.substring((len - 3) * 2, (len - 3) * 2 + 6);
        Log.e(TAG, "长度" + len + ",obu状态:" + strVstObuStatus);
        int nObuStatus = Integer.parseInt(strVstObuStatus.substring(2, 4), 16);
        if ((nObuStatus & 0x80) == 0x80)
            nCardNoExist = 1;
        else
            nCardNoExist = 0;

        nIsObuOneChip = Integer.parseInt(strVstObuStatus.substring(0, 2), 16);
        if ((nIsObuOneChip & 0xF0) == 0x40)
            nIsObuOneChip = 1;
        else
            nIsObuOneChip = 0;
        if (nIsObuOneChip == 1) return 0;

        Log.e(TAG, "nIsObuOneChip:" + nIsObuOneChip);

        if ((flag & 0x40) != 0x40) {// 判断是否存在预读
            if (pVst[offset] == 40) {
                offset++;
                strVst0015 = strVst.substring(offset * 2, offset * 2
                        + VST_15_LEN * 2);
                int nCardVersion = Integer.parseInt(strVst0015.substring(9 * 2, 10 * 2), 16);
                if ((nCardVersion & 0x40) == 0x40)
                    nCardVersionType = 1;
                else
                    nCardVersionType = 0;
                if ((nCardVersion & 0x50) == 0x50)
                    nCardAlgId = 4;
                else
                    nCardAlgId = 0;
                if (strVst0015.substring(0, 8).equals("B9E3CEF7"))
                    nCardIsGx = 1;
                else
                    nCardIsGx = 0;
                offset += VST_15_LEN;
                strVst0002 = strVst.substring(offset * 2, offset * 2 + 4 * 2);
            } else {
                strVst0015 = "";
                strVst0002 = "";
            }
            Log.e(TAG, "预读取OBU卡片信息,0015文件数据为:" + strVst0015);

        }
        LoadObuData();
        LoadCardData();
        return 0;
    }

    public static ObuBean getObuBean() {
        return obuBean;
    }

    public static void setObuBean(ObuBean obuBean) {
        OfflineOperate.obuBean = obuBean;
    }

    static ObuBean obuBean;

    public static void LoadObuData() {
        obuBean = new ObuBean();
        Log.e(TAG, "OBU防拆状态:" + GetObuStatus());
        Log.e(TAG, "OBUMAC:" + GetOBUMAC());
        obuBean.setObuStatus(GetObuStatus());
        obuBean.setObuMAC(GetOBUMAC());

        Log.e(TAG, "OBU发行方标识:" + HexUtil.HexToAsciiString(GetOBUArea()));
        Log.e(TAG, "OBU协约类型:" + GetObuContractType());

        obuBean.setObuArea(HexUtil.HexToAsciiString(GetOBUArea()));
        obuBean.setObuContractType(GetObuContractType());

        Log.e(TAG, "OBU合同版本:" + GetObuContract());
        Log.e(TAG, "OBU合同序列号:" + GetOBUSerialNumber());
        obuBean.setObuContract(GetObuContract());
        obuBean.setObuSerialNumber(GetOBUSerialNumber());

        Log.e(TAG, "OBU生效日期:" + convertDate(GetObuDate().substring(0, 8)));
        Log.e(TAG, "OBU失效日期:" + convertDate(GetObuDate().substring(8, 16)));
        Log.e(TAG, "OBU电量:" + GetObuBattery());

        obuBean.setObuDateStart(convertDate(GetObuDate().substring(0, 8)));
        obuBean.setObuDateEnd(convertDate(GetObuDate().substring(8, 16)));
        obuBean.setObuBattery(GetObuBattery());
    }


    public static CardBean getCardBean() {
        return cardBean;
    }

    public static void setCardBean(CardBean cardBean) {
        OfflineOperate.cardBean = cardBean;
    }

    static CardBean cardBean;

    public static void LoadCardData() throws Exception {
        cardBean = new CardBean();
        Log.e(TAG, "卡片发行商:" + GetCardIssuer());
        Log.e(TAG, "卡片类型:" + GetCardType());
        Log.e(TAG, "卡片版本:" + GetCardVersion());
        cardBean.setCardIssuer(GetCardIssuer());
        cardBean.setCardType(GetCardType());
        cardBean.setCardVersion(GetCardVersion());

        Log.e(TAG, "卡号:" + GetCardSerialNumber());
        Log.e(TAG, "卡内车牌号:" + GetCardVlp());
        Log.e(TAG, "卡内车牌颜色:" + GetCardVehicleColor());

        cardBean.setCardSerialNumber(GetCardSerialNumber());
        cardBean.setCardVlp(GetCardVlp());
        cardBean.setCardVehicleColor(GetCardVehicleColor());

        Log.e(TAG, "卡内用户类型" + GetCardUserType());
        Log.e(TAG, "余额:" + GetCardBalance());

        cardBean.setCardUserType(GetCardUserType());
        cardBean.setCardBalance(GetCardBalance());


        Log.e(TAG, "卡内有效期开始:" + GetCardDate1());
        Log.e(TAG, "卡内有效期结束:" + GetCardDate2());
        cardBean.setCardDateStart(GetCardDate1());
        cardBean.setCardDateEnd(GetCardDate2());


    }


    public static String GetCardIssuer() throws Exception {
        // Log.i("test","strVst0015="+strVst0015);
        if (strVst0015.equals(""))
            return "";
        return HexUtil.HexToAsciiString(strVst0015.substring(0, 8 * 2));
    }

    public static String GetCardType() {
        if (strVst0015.equals(""))
            return "";
        return GetCardType(strVst0015.substring(8 * 2, 9 * 2));
    }

    public static String GetCardType(String type) {
        String str = "";
        if ("16".equals(type)) {
            str = "储值卡";
        } else if ("17".equals(type)) {
            str = "记账卡";
        } else {
            str = "未定义" + type;
        }
        return str;
    }

    public static String GetCardVersion() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(9 * 2, 10 * 2);
    }

    public static String GetCardNetNumber() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(10 * 2, 12 * 2);
    }

    public static String GetCardSerialNumber() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(12 * 2, 20 * 2);
    }

    public static String GetCardDate1() {
        if (strVst0015.equals(""))
            return "";
        return convertDate(strVst0015.substring(20 * 2, 20 * 2 + 8));
    }

    public static String GetCardDate2() {
        if (strVst0015.equals(""))
            return "";
        return convertDate(strVst0015.substring(20 * 2 + 8, 20 * 2 + 16));// 28*2
    }

    public static String GetCardVlp() throws Exception {
        if (strVst0015.equals(""))
            return "";
        return HexUtil.HexToAsciiString(strVst0015.substring(28 * 2,
                28 * 2 + 24));// 40*2
    }

    public static String GetCardUserType() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(40 * 2, 41 * 2);
    }

    public static String GetCardVehicleColor() {
        if (strVst0015.equals(""))
            return "";
        String strResult = "";
        String strCardArea;
        if (nCardVersionType == 1) {
            strResult = vehicleColor("00"
                    + strVst0015.substring(41 * 2, 42 * 2));
        } else {
            strCardArea = HexUtil.HexToAsciiString(strVst0015.substring(0, 8));

            if (strCardArea.equals("云南")) {
                int nCol = (HexUtil.StringToByte(strVst0015.substring(42 * 2,
                        43 * 2)) >>> 4) & 0x0F;
                strResult = vehicleColor(nCol);
            } else if (strCardArea.equals("山东")) {
                // strResult = vehicleColor(strVst0015.substring(41*2, 43*2));
                int nCol = (HexUtil.StringToByte(strVst0015.substring(41 * 2,
                        42 * 2))) & 0xFF;
                strResult = vehicleColor("00" + HexUtil.ByteToString(nCol));
            } else if (strCardArea.equals("浙江") || strCardArea.equals("福建")
                    || strCardArea.equals("安徽") || strCardArea.equals("江苏")
                    || strCardArea.equals("江西")) {
                strResult = vehicleColor(strVst0015.substring(41 * 2, 43 * 2));
            } else {
                strResult = "未定义";
            }
        }
        return strResult;
    }

    public static String GetCardBalance() {
        if (strVst0002.equals(""))
            return "";
        long nBalance = Long.parseLong(strVst0002, 16);
        return String.valueOf(nBalance / 100) + "."
                + String.valueOf(nBalance % 100) + "元";
    }

    public static String GetObuContractType() {
        return strVstSystemFile.substring(8 * 2, 9 * 2);
    }

    public static String GetObuBattery() {
        String strBattery;
        byte byteStatus = HexUtil.StringToByte(strVstObuStatus.substring(2, 4));
        if ((byteStatus & 0x01) == 0x01)
            strBattery = "低电";
        else
            strBattery = "正常";

        return strBattery;
    }


    public static String GetObuDate() {
        return strVstSystemFile.substring(18 * 2, 18 * 2 + 16);
    }

    /**
     * 把时间拆分加上年月日
     *
     * @param time
     * @return
     */
    public static String convertDate(String time) {
        if (time.equals(""))
            return "";
        String date = null;
        // 年份
        String str = time.substring(0, 4);
        // 月份
        String year = time.substring(4, 6);
        // 日期
        String day = time.substring(6, 8);
        date = str + "年" + year + "月" + day + "日";
        return date;
    }

    public static String GetObuStatus() {
        String strStatus;
        byte byteStatus = HexUtil.StringToByte(strVstObuStatus.substring(2, 4));
        Log.e("test", "obustatus=" + byteStatus);
        if ((byteStatus & 0x02) == 0x02)
            strStatus = "已拆";
        else
            strStatus = "未拆";

        return strStatus;
    }

    /**
     * 获取Vst中系统信息(合同序列号)
     *
     * @return
     */
    public static String GetOBUSerialNumber() {
        return strVstSystemFile.substring(20, 36);

    }

    public static String GetOBUArea() {
        return strVstSystemFile.substring(0, 8);

    }

    public static String GetOBUMAC() {
        return strMacId;

    }

    public static String GetIC0015() {
        return strVst0015;
    }

    public String GetIC0002() {
        return strVst0002;
    }

    static int offset = 0;
    // 车辆核定载质量_车轮
    public static String VCarAllowableload_VWheel;
    // 整备质量_车轴数
    public static String VCarcurbweight_VAxis;
    // 车辆总质量_车轴距
    public static String VCartotalmass_VAxisWidth;
    // 核定载人数_载重
    public static String VCarnumberofpeople_VWeight;
    // 车辆识别号_车辆发动机号
    public static String VCarVehicle_VEngineSN;


    public static String VCarVLP = null;
    public static String VCarVLPC = null;
    public static String VCarVLPC_1 = null;
    public static String VCarVClass = null;
    public static String VCarVUserType = null;
    public static String VCarVSize = null;
    public static String VCarVSize2 = null;
    public static String VCarVDescribe = null;

    public static String GetObuContract() {
        return strVstSystemFile.substring(9 * 2, 10 * 2);
    }

    public static CarKCBean getCarKCBean() {
        return carKCBean;
    }

    public static void setCarKCBean(CarKCBean carKCBean) {
        OfflineOperate.carKCBean = carKCBean;
    }

    static CarKCBean carKCBean;

    /**
     * 客车车辆解析方式
     *
     * @param strVehicle
     * @param vehicleLen
     * @throws Exception
     */
    public static void SortVehicleKC(String strVehicle, int vehicleLen)
            throws Exception {
        carKCBean = new CarKCBean();
        offset = 0;
        // 1.车牌号
        VCarVLP = HexUtil.HexToAsciiString(strVehicle
                .substring(offset, offset + 24));

        carKCBean.setCarVLP(VCarVLP);
        offset += 24;
        if (offset >= vehicleLen)
            return;
        //2. 车牌颜色
        VCarVLPC = vehicleColor(strVehicle.substring(offset + 2, offset + 4));

        carKCBean.setCarVLPC(VCarVLPC);
        offset += 4;
        if (offset >= vehicleLen)
            return;
        // 3.车型
        VCarVClass = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
//        String VClass2 = String.valueOf(Integer.parseInt(
//                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        carKCBean.setCarVClass(VCarVClass);
        if (offset >= vehicleLen)
            return;




        // 4.车辆客户类型
        VCarVUserType = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;

        carKCBean.setCarVUserType(VCarVUserType);
        if (offset >= vehicleLen)
            return;
        // 5.车辆尺寸
        String cheliangchicun = strVehicle.substring(offset, offset + 12);
//            VCarVSize = "车辆尺寸：" + vehicleSize2(cheliangchicun, 1);
//            VCarVSize2 = "车辆尺寸：" + vehicleSize3(cheliangchicun, 2);
        VCarVSize = vehicleSize2(cheliangchicun, 1);
        VCarVSize2 = vehicleSize3(cheliangchicun, 2);
        offset += 12;
        carKCBean.setCarVSize(VCarVSize);
        carKCBean.setCarVSize2(VCarVSize2);
        if (offset >= vehicleLen)
            return;
        // 6.车辆核定载质量(KG)

        VCarAllowableload_VWheel = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 6), 16));
        offset += 6;
        carKCBean.setCarAllowableload_VWheel(VCarAllowableload_VWheel);
        if (offset >= vehicleLen)
            return;
        //7. 整备质量(KG)
        VCarcurbweight_VAxis = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 6), 16));
        carKCBean.setCarcurbweight_VAxis (VCarcurbweight_VAxis);
        offset += 6;
        if (offset >= vehicleLen)
            return;
        // 8.车辆总质量(KG)
        VCartotalmass_VAxisWidth = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 6), 16));

        offset += 6;
        carKCBean.setCartotalmass_VAxisWidth (VCartotalmass_VAxisWidth);
        if (offset >= vehicleLen)
            return;
        // 9.核定载人数
        VCarnumberofpeople_VWeight =
                String.valueOf(Integer.parseInt(
                        strVehicle.substring(offset, offset + 2), 16));


        offset += 2;
        carKCBean.setCarnumberofpeople_VWeight (VCarnumberofpeople_VWeight);
        if (offset >= vehicleLen)
            return;

        // 10.车辆识别号

        VCarVehicle_VEngineSN = HexUtil.HexToAsciiString(strVehicle.substring(offset,
                offset + 34));
        offset += 34;
        carKCBean.setCarVehicle_VEngineSN (VCarVehicle_VEngineSN);
        if (offset >= vehicleLen)
            return;

        // 11.车辆特征描述
        String substring = strVehicle.substring(offset, offset + 32);

        VCarVDescribe = HexUtil.HexToAsciiString(substring);

        offset += 32;
        carKCBean.setCarVDescribe (VCarVDescribe);

    }

    public static CarHCBean getCarHCBean() {
        return carHCBean;
    }

    public static void setCarHCBean(CarHCBean carHCBean) {
        OfflineOperate.carHCBean = carHCBean;
    }

    static CarHCBean carHCBean ;
    /**
     * 货车解析
     *
     * @param strVehicle
     * @param vehicleLen
     * @throws Exception
     */
    public static void  SortVehicleHC(String strVehicle, int vehicleLen)
            throws Exception {
        carHCBean=new CarHCBean();

        offset = 0;
        // 1.车牌号
        VCarVLP = HexUtil.HexToAsciiString(strVehicle
                .substring(offset, offset + 24));
        offset += 24;
        carHCBean.setCarVLP(VCarVLP);
        if (offset >= vehicleLen)
            return;
        //2. 车牌颜色
        VCarVLPC = vehicleColor(strVehicle.substring(offset + 2, offset + 4));
        carHCBean.setCarVLPC(VCarVLPC);

        offset += 4;
        if (offset >= vehicleLen)
            return;
        // 3.车型
        VCarVClass = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));

        offset += 2;
        carHCBean.setCarVClass(VCarVClass);
        if (offset >= vehicleLen)
            return;
        offset = 30;

        if (offset >= vehicleLen)
            return;
        //21.车辆客户类型
        VCarVUserType = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        carHCBean.setCarVUserType(VCarVUserType);
        if (offset >= vehicleLen)
            return;
        //22.车辆尺寸
//            VCarVSize = "车辆尺寸：" + vehicleSize2(strVehicle.substring(offset, offset + 8), 1);
//            VCarVSize2 = "车辆尺寸：" + vehicleSize2(strVehicle.substring(offset, offset + 8), 2);
        VCarVSize = vehicleSize2(strVehicle.substring(offset, offset + 8), 1);
        VCarVSize2 = vehicleSize2(strVehicle.substring(offset, offset + 8), 2);
        carHCBean.setCarVSize(VCarVSize);
        carHCBean.setCarVSize2(VCarVSize2);
        offset += 8;
        if (offset >= vehicleLen)
            return;
        //23.车轮数
        VCarAllowableload_VWheel = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        carHCBean.setCarAllowableload_VWheel(VCarAllowableload_VWheel);
        if (offset >= vehicleLen)
            return;
        //24.车轴数
        VCarcurbweight_VAxis = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        carHCBean.setCarcurbweight_VAxis (VCarcurbweight_VAxis);

        if (offset >= vehicleLen)
            return;
        //25.车轴距
        VCartotalmass_VAxisWidth = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 4), 16));
        offset += 4;
        carHCBean.setCartotalmass_VAxisWidth (VCartotalmass_VAxisWidth);
        if (offset >= vehicleLen)
            return;
        //26.座位数、载重
        VCarnumberofpeople_VWeight = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 6), 16));
        offset += 6;
        carHCBean.setCarnumberofpeople_VWeight (VCarnumberofpeople_VWeight);
        if (offset >= vehicleLen)
            return;
        //27.车辆特征描述
        VCarVDescribe = HexUtil.HexToAsciiString(strVehicle.substring(offset,
                offset + 32));
        offset += 32;
        carHCBean.setCarVDescribe (VCarVDescribe);
        if (offset >= vehicleLen)
            return;
        //28.车辆发动机号
        VCarVehicle_VEngineSN = HexUtil.HexToAsciiString(strVehicle.substring(offset,
                offset + 32));
        offset += 32;
        carHCBean.setCarVehicle_VEngineSN (VCarVehicle_VEngineSN);

    }


    public static String vehicleSize2(String size, int type) throws Exception {
        String strSize = "";
        if (type == 1 || type == 0)
            strSize += String.valueOf(Integer.parseInt(size.substring(0, 4), 16));
        if (type == 2 || type == 0) {
            strSize += String.valueOf(Integer.parseInt(size.substring(4, 6), 16)) + " ";
            strSize += String.valueOf(Integer.parseInt(size.substring(6, 8), 16));
        }
        return strSize;
    }

    public static String vehicleSize3(String size, int type) throws Exception {
        String strSize = "";
        if (type == 1 || type == 0)
            strSize += String.valueOf(Integer.parseInt(size.substring(0, 4), 16));
        if (type == 2 || type == 0) {
            strSize += String.valueOf(Integer.parseInt(size.substring(4, 8), 16)) + " ";
            strSize += String.valueOf(Integer.parseInt(size.substring(8, 12), 16));
        }
        return strSize;
    }

    public static String vehicleColor(String color) {

        int nCol = HexUtil.StringToByte(color);
        String colo = vehicleColor(nCol);
        return colo;
    }

    public static String vehicleColor(int nColo) {
        String colo = "";
        switch (nColo) {
            case 0:
                colo = "蓝";
                break;
            case 1:
                colo = "黄";
                break;
            case 2:
                colo = "黑";
                break;
            case 3:
                colo = "白";
                break;
            case 4:
                colo = "渐变绿";
                break;
            case 5:
                colo = "黄绿双拼";
                break;
            case 6:
                colo = "蓝白渐变";
                break;

            case 7:
                colo = "临时牌照";
                break;

            case 9:
                colo = "未定义";
                break;

            case 11:
                colo = "绿";
                break;
            case 12:
                colo = "红";
                break;
            default:
                colo = "未定义类型0x" + HexUtil.LongToHexString(nColo, 2, 0);
        }
        return colo;
    }

    static String TAG = "大智测试GetSystem";
    /**
     * 读取硬件版本号,需要补全
     * @throws Exception
     */
    public static String SendReadVersion( )
            throws Exception {
        String rsuVerison = OperationBySerialPort.getInstance().getRsuVerison();
        return rsuVerison;

    }

    public static void JLOffGetSecure() throws Exception {
        int psamSoltSignChip = OfflineSetting.psamSoltSignChip;
        int vehicleLen = OfflineSetting.vehicleLen;
        String KeyType = OfflineSetting.KeyType;
        //车辆密文
        String VehicleCiphertextData = "";
        //密钥分散指令
        String RQKeyDispersionCmd = "";

        String RQVehicleCmd = "";
        //鉴别码1
        String AuthCode1 = "";
        //鉴别码2
        String AuthCode2;
        //车辆明文
        String VehicleText = "";

        String strRandom = "";
        try {
            //1.Psam卡复位
            Log.e(TAG, "1.1 PSAM卡复位开始");
            SDK_PSAM.PsamReset(psamSoltSignChip);
            Log.e(TAG, "1.2 PSAM卡复位结束");
        } catch (Exception e) {
            throw new NumberFormatException("Psam卡复位" + psamSoltSignChip
                    + e.getMessage());
        }


        try {
            //2.读取车辆信息密文
            Log.e(TAG, "2.1 SDK读取车辆信息密文开始");
            strRandom = HexUtil.GetRand(8);
            GetSecureBean secure = SDK_RSU.getSecure(vehicleLen, strRandom);
            if (secure.getCode() == 0) {
                VehicleCiphertextData = secure.getFile();
                Log.e(TAG, "2.2 SDK车辆信息密文:" + secure.getFile());
                Log.e(TAG, "2.3 SDK读取车辆信息密文结束");

            } else {
                throw new NumberFormatException("读取车辆信息密文失败");

            }
        } catch (Exception e) {
            throw new NumberFormatException("读取车辆信息密文" + psamSoltSignChip
                    + e.getMessage());
        }
        try {
            //3.PSAM卡选DF01
            Log.e(TAG, "3.1 PSAM卡选DF01开始");
            String RQSelectDF01ContentsCmd = "00A4000002DF01";
            Log.e(TAG, "3.2 PSAM选DF01目录指令:" + RQSelectDF01ContentsCmd);
            String RESelectDF01ContentsCmd = SDK_PSAM.PsamCos(psamSoltSignChip, RQSelectDF01ContentsCmd);
            if (!RESelectDF01ContentsCmd.contains("9000")) {
                throw new NumberFormatException("PSAM选DF01目录异常，返回值为:" + RESelectDF01ContentsCmd);
            }
            Log.e(TAG, "3.3 PSAM卡选DF01结束");
        } catch (Exception e) {
            throw new NumberFormatException("PSAM卡选DF01" + psamSoltSignChip
                    + e.getMessage());
        }


        try {
            //4.Psam卡密钥分散
            Log.e(TAG, "4.1 PSAM卡密钥分散拼装指令开始");
            if (KeyType.equals("59")) {
                Log.e(TAG, "4.2 GetOBUSerialNumber:" + GetOBUSerialNumber());
                Log.e(TAG, "4.3 GetOBUArea:" + GetOBUArea());
                RQKeyDispersionCmd = "801A590310" + GetOBUSerialNumber() + GetOBUArea()
                        + GetOBUArea();
            } else
                RQKeyDispersionCmd = "801A390308" + GetOBUSerialNumber();
            Log.e(TAG, "4.4 PSAM卡密钥分散指令为:" + RQKeyDispersionCmd);
            String REKeyDispersionCmd = SDK_PSAM.PsamCos(psamSoltSignChip, RQKeyDispersionCmd);
            if (!REKeyDispersionCmd.contains("9000")) {
                throw new NumberFormatException("Psam卡密钥分散异常，返回值为:" + REKeyDispersionCmd);
            }

            Log.e(TAG, "4.5 PSAM卡密钥分散结束，返回值为:" + REKeyDispersionCmd);
        } catch (Exception e) {
            throw new NumberFormatException("Psam卡密钥分散" + psamSoltSignChip
                    + e.getMessage());
        }


        try {
            //5.解密车辆
            Log.e(TAG, "5.1 PSAM解密车辆开始");
            RQVehicleCmd = "80FA8000";
            RQVehicleCmd += HexUtil.ByteToString(VehicleCiphertextData.length() / 2);

            RQVehicleCmd += VehicleCiphertextData;
            Log.e(TAG, "5.2 PSAM解密车辆指令为" + RQVehicleCmd);
            String REVehicleCmd = SDK_PSAM.PsamCos(psamSoltSignChip, RQVehicleCmd);
            if (!REVehicleCmd.contains("9000")) {
                throw new NumberFormatException("解密车辆异常，返回值为:" + REVehicleCmd);
            }


            //1获得鉴别码
            AuthCode1 = REVehicleCmd.substring(2, 2 + 16);
            Log.e(TAG, "5.4 车辆鉴别码,鉴别码为:" + AuthCode1);
            // 解析车辆明文信息
            VehicleText = REVehicleCmd.substring(18, 18 + vehicleLen * 2);
            Log.e(TAG, "5.5 车辆明文为:" + VehicleText);
            Log.e(TAG, "5.6 PSAM解密车辆结束" + REVehicleCmd);
        } catch (Exception e) {
            throw new NumberFormatException("解密车辆" + psamSoltSignChip + e.getMessage());

        }


        try {
            //7.计算鉴别码前密钥分散
            Log.e(TAG, "6.1 PSAM计算鉴别码，密钥分散开始");
            Log.e(TAG, "6.2 PSAM密钥分散指令:" + RQKeyDispersionCmd);
            String RQKeyDispersionCmd2 = SDK_PSAM.PsamCos(psamSoltSignChip, RQKeyDispersionCmd);
            if (!RQKeyDispersionCmd2.contains("9000")) {
                throw new NumberFormatException("计算鉴别码，密钥分散异常，返回值为:" + RQKeyDispersionCmd2);
            }
            Log.e(TAG, "6.3 PSAM计算鉴别码，密钥分散结束，返回值为:" + RQKeyDispersionCmd2);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM鉴别码分散," + e.getMessage());

        }


        try {

            //8.计算鉴别码
            Log.e(TAG, "7.1 PSAM计算鉴别码2开始");
            String RQAuthenticationCodeCmd = "80FA0800" + HexUtil.ByteToString(vehicleLen + 8)
                    + strRandom + VehicleText;
            Log.e(TAG, "7.2 PSAM计算鉴别码2指令为:" + RQAuthenticationCodeCmd);
            String REAuthenticationCodeCmd = SDK_PSAM.PsamCos(psamSoltSignChip, RQAuthenticationCodeCmd);
            if (!REAuthenticationCodeCmd.contains("9000")) {
                throw new NumberFormatException("PSAM计算鉴别码2异常，返回值为:" + REAuthenticationCodeCmd);
            }


            Log.e(TAG, "7.3 PSAM计算鉴别码2返回数据:" + REAuthenticationCodeCmd);
            AuthCode2 = REAuthenticationCodeCmd.substring(0, REAuthenticationCodeCmd.length() - 4);
            Log.e(TAG, "7.4 鉴别码2为:" + AuthCode2);
            Log.e(TAG, "7.5 PSAM计算鉴别码2结束");
            Log.e(TAG, "7.6 鉴别码1=" + AuthCode1 + ",鉴别码2=" + AuthCode2);
            if (!AuthCode2.equals(AuthCode1)) {
                throw new NumberFormatException("鉴别码错误");
            }
        } catch (Exception e) {
            throw new NumberFormatException("PSAM计算鉴别码" + psamSoltSignChip
                    + e.getMessage());
        }
        try {
            //8.解析车辆
            Log.e(TAG, "8.1 解析车辆开始");

            String s = GetObuContract();
              carAllBean=new CarAllBean();
            if (s.equals("40")) {
                Log.e(TAG, "8.1 解析车辆客车" );
                SortVehicleKC(VehicleText, vehicleLen * 2);
                carAllBean.setType("1");
                carAllBean.setCarKCBean(getCarKCBean());
            } else {
                Log.e(TAG, "8.1 解析车辆货车");
                SortVehicleHC(VehicleText, vehicleLen * 2);
                carAllBean.setType("2");
                carAllBean.setCarHCBean(getCarHCBean());
            }



            Log.e(TAG, "8.2 解析车辆结束");
        } catch (Exception e) {
            throw new NumberFormatException("解析车辆" + psamSoltSignChip + e.getMessage());

        }


    }

    public static CarAllBean getCarAllBean() {
        return carAllBean;
    }

    public static void setCarAllBean(CarAllBean carAllBean) {
        OfflineOperate.carAllBean = carAllBean;
    }

    static  CarAllBean carAllBean;

    /**
     * OBU脱机激活
     * pre:是否需要预检测 1需要  2不需要
     * strExminObuMac :传入预检测OBU的MAC
     */
    public static void JLOffActive(String pre,String strExminObuMac ) throws Exception {
        String DATA = "00";
        String WriteKeyId = OfflineSetting.WriteKeyId;
        String WritePsamDir = OfflineSetting.WritePsamDir;
        String WriteKeyType = OfflineSetting.WriteKeyType;
        int nIsSm4 = OfflineSetting.nIsSm4;


        if (nCardNoExist == 1) {
            if (strVst0015.equals("")) {
                throw new NumberFormatException("请插IC卡！");
            }
        }
        String OBUMAC = GetOBUMAC();
        if (pre.equals("1")) {
        if (OBUMAC.equals(strExminObuMac) == false)
            throw new NumberFormatException("读OBU与预检测的不一致！");
        }

        try {
            JLOffGetSecure();
        } catch (Exception e) {
            throw new NumberFormatException("读车辆异常:" + e);
        }
        if (nIsCheckEsamIccVersion != 0) {
            if (nObuVersionType != nCardVersionType) {
                throw new NumberFormatException("OBU版本和IC卡版本不一致！OBU版本："
                        + GetObuContract() + "  IC卡版本：" + GetCardVersion());
            }
        }
        String strTmpWriteKeyId = WriteKeyId;


        ESAM_WRITEDATA(1, 1, WritePsamDir, WriteKeyType, strTmpWriteKeyId, DATA, 26, nIsSm4);
    }

    /**
     * 更新ESAM文件
     *
     * @param strPsamSlot 卡片通道 1 2
     * @param isSys       非0表示更新系统信息，0表示更新车辆信息
     * @param PsamDir     目录 例：DF01,DF02,DF03
     * @param KeyType     密钥类型, 例：46,48,26,28
     * @param KeyId
     * @param Data        要更新的数据  第几位开始
     * @param nOffset     数据偏移
     * @throws Exception
     */
    public static void ESAM_WRITEDATA(int strPsamSlot, int isSys, String PsamDir, String KeyType,
                                      String KeyId, String Data, int nOffset, int nIsSm4) throws Exception {
        String RQESAMSelectDirectoryCmd = "";
        String RESelectContentsCmd = "";
        String RQGetMACCmd = "";
        String RQKeyDispersionCmd;
        String REKeyDispersionCmd;

        String REGetMAC = "";
        //取的随机数
        String RandomNumber;
        String KeyID = "";
        String Value = Data;
        String strWrite = "";

        try {
            // 1、ESAM选目录
            Log.e(TAG, "1.1 ESAM选目录开始");
            if (isSys != 0) {
                KeyID = KeyId;
                RQESAMSelectDirectoryCmd = "00A40000023F00";
                // 强行修改分散因子
                if (nOffset < 18)
                    Value = GetOBUArea() + Data.substring(8, 20)
                            + GetOBUSerialNumber() + Data.substring(36);
            } else {
                KeyID = HexUtil.ByteToString((HexUtil.StringToByte(KeyId) + 1));
                RQESAMSelectDirectoryCmd = "00A4000002DF01";
            }
            Log.e(TAG, "1.2 ESAM选目录指令:" + RQESAMSelectDirectoryCmd);
            TransferChannel_res REESAMSelectDirectoryCmd = SDK_RSU.SendTransferChannel(2, RQESAMSelectDirectoryCmd);
            String REESAMSelectDirectoryCmdData = REESAMSelectDirectoryCmd.getData();
            if (!REESAMSelectDirectoryCmdData.contains("9000")) {
                throw new NumberFormatException("ESAM选目录异常，返回值为:" + REESAMSelectDirectoryCmdData);
            }

            Log.e(TAG, "1.3 ESAM选目录结束,返回值为" + REESAMSelectDirectoryCmdData);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM选DF01," + e.getMessage());
        }


        try {
            // 2、ESAM选EF01
            Log.e(TAG, "2.1 ESAM选EF01开始");
            String RQESAMSelectEF01DirectoryCmd = "00A4000002EF01";
            Log.e(TAG, "2.2 ESAM选EF01指令:" + RQESAMSelectEF01DirectoryCmd);
            TransferChannel_res REESAMSelectEF01DirectoryCmd = SDK_RSU.SendTransferChannel(2, RQESAMSelectEF01DirectoryCmd);

            String REESAMSelectEF01DirectoryCmdData = REESAMSelectEF01DirectoryCmd.getData();
            if (!REESAMSelectEF01DirectoryCmdData.contains("9000")) {
                throw new NumberFormatException("ESAM选EF01异常，返回值为:" + REESAMSelectEF01DirectoryCmdData);
            }

            Log.e(TAG, "2.3 ESAM选EF01结束，返回值为:" + REESAMSelectEF01DirectoryCmdData);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM选EF01" + e.getMessage());
        }


        try {
            // 3、ESAM取随机数
            Log.e(TAG, "3.1 ESAM取随机数开始");
            String RQESAMGetNumberCmd = "0084000004";
            Log.e(TAG, "3.2 ESAM取随机数指令:" + RQESAMGetNumberCmd);
            TransferChannel_res REESAMGetNumberCmd = SDK_RSU.SendTransferChannel(2, RQESAMGetNumberCmd);

            String REESAMGetNumberCmdData = REESAMGetNumberCmd.getData();
            if (!REESAMGetNumberCmdData.contains("9000")) {
                throw new NumberFormatException("ESAM取随机数异常，返回值为:" + REESAMGetNumberCmdData);
            }
            Log.e(TAG, "3.3 ESAM取随机数结束,返回值为:" + REESAMGetNumberCmdData);
            RandomNumber = REESAMGetNumberCmdData.substring(2, REESAMGetNumberCmdData.length() - 4);
            Log.e(TAG, "3.4 ESAM取随机数,随机数为:" + RandomNumber);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM取随机数," + e.getMessage());
        }


        try {
            // 4、PSAM选应用目录
            Log.e(TAG, "4.1 ESAM选目录开始");

            String RQPsamSelectContentsCmd = "00A4000002" + PsamDir;
            Log.e(TAG, "4.2 ESAM选目录指令:" + RQPsamSelectContentsCmd);

            String REPsamSelectContentsCmd = SDK_PSAM.PsamCos(strPsamSlot, RQPsamSelectContentsCmd);
            if (!REPsamSelectContentsCmd.contains("9000")) {
                throw new NumberFormatException("ESAM选目录异常，返回值为:" + REPsamSelectContentsCmd);
            }

            Log.e(TAG, "4.3 ESAM选目录结束,应答为:" + REPsamSelectContentsCmd);
        } catch (Exception e) {
            throw new NumberFormatException("选" + PsamDir + ",PSAM" + strPsamSlot + e.getMessage());

        }


        try {
            // 5、PSAM密钥分散
            Log.e(TAG, "5.1 ESAM密钥分散开始");
            if (KeyType.substring(0, 1).equals("4"))
                RQKeyDispersionCmd = "801A" + KeyType + KeyID + "10" + GetOBUSerialNumber()
                        + GetOBUArea() + GetOBUArea();
            else
                RQKeyDispersionCmd = "801A" + KeyType + KeyID + "08" + GetOBUSerialNumber();

            Log.e(TAG, "5.2 ESAM密钥分散指令:" + RQKeyDispersionCmd);

            REKeyDispersionCmd = SDK_PSAM.PsamCos(strPsamSlot, RQKeyDispersionCmd);

            if (!REKeyDispersionCmd.equals("9000")) {
                throw new NumberFormatException("密钥分散异常，返回值为:" + REKeyDispersionCmd);
            }
            Log.e(TAG, "5.3 ESAM密钥分散结束,返回值:" + REKeyDispersionCmd);
        } catch (Exception e) {
            throw new NumberFormatException("密钥分散,PSAM" + strPsamSlot
                    + e.getMessage());
        }


        try {
            // 6、PSAM计算MAC
            Log.e(TAG, "6.1 PSAM计算MAC开始");
            Log.e(TAG, "6.2 写入的数据:" + Value);

            strWrite = "04D681" + HexUtil.ByteToString(nOffset) + HexUtil.ByteToString(Data.length() / 2 + 4) + Value;
            Log.e(TAG, "6.3 Test1:" + strWrite);
            if (nIsSm4 == 0) {
                RQGetMACCmd = HexUtil.StringApp80(strWrite, 1, 8);
                Log.e(TAG, "6.4 Test2:" + RQGetMACCmd);
                String RQGetMACCmd2 = "80FA0500"
                        + HexUtil.ByteToString(8 + RQGetMACCmd.length() / 2)
                        + RandomNumber + "00000000" + RQGetMACCmd;

                Log.e(TAG, "6.5 PSAM计算MAC指令:" + RQGetMACCmd2);
                String REGetMACCmd = SDK_PSAM.PsamCos(strPsamSlot, RQGetMACCmd2);
                String REGetMACCmdCode = REGetMACCmd.substring(REGetMACCmd.length() - 4, REGetMACCmd.length());
                Log.e(TAG, "6.6 PSAM计算MAC结束,返回值:" + REGetMACCmd);
                if (!REGetMACCmdCode.equals("9000")) {
                    throw new NumberFormatException("计算MAC返回值异常，返回值为:" + REGetMACCmd);
                }
                REGetMAC = REGetMACCmd.substring(0, REGetMACCmd.length() - 4);
                Log.e(TAG, "6.7 PSAM计算MAC结束,MAC为:" + REGetMAC);
            } else {
                RQGetMACCmd = HexUtil.StringApp80(strWrite, 1, 16);
                Log.e(TAG, "6.8 TEST3:" + RQGetMACCmd);


                String RQGetMACCmd2 = "80FA0500"
                        + HexUtil.ByteToString(16 + RQGetMACCmd.length() / 2)
                        + RandomNumber + "000000000000000000000000" + RQGetMACCmd;

                Log.e(TAG, "6.9 PSAM计算MAC指令:" + RQGetMACCmd2);
                String REGetMACCmd = SDK_PSAM.PsamCos(strPsamSlot, RQGetMACCmd2);
                if (!REGetMACCmd.contains("9000")) {
                    throw new NumberFormatException("计算MAC返回值异常，返回值为:" + REGetMACCmd);
                }

                Log.e(TAG, "6.10 PSAM计算MAC结束,返回值:" + REGetMACCmd);
                REGetMAC = REGetMACCmd.substring(0, REGetMACCmd.length() - 4);
                Log.e(TAG, "6.11 PSAM计算MAC为:" + REGetMAC);
            }
        } catch (Exception e) {
            throw new NumberFormatException("PSAM算MAC:" + e.getMessage());

        }


        try {
            Log.e(TAG, "7.1 ESAM更新文件开始");
            String RQWriteDataCmd = strWrite + REGetMAC;
            // 6、ESAM更新文件
            Log.e(TAG, "7.2 ESAM更新文件,数据为:" + RQWriteDataCmd);
            TransferChannel_res REWriteDataCmd = SDK_RSU.SendTransferChannel(2, RQWriteDataCmd);
            String REWriteDataCmdData = REWriteDataCmd.getData();
            if (!REWriteDataCmdData.contains("9000")) {
                throw new NumberFormatException("ESAM更新异常，返回值为:" + REWriteDataCmdData);
            }
            Log.e(TAG, "7.3 ESAM更新文件结束,返回值:" + REWriteDataCmdData);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM更新," + e.getMessage());
        }

    }


    /**
     * 零元消费
     *
     * @throws Exception
     */
    public static void JLOffPay(String number) throws Exception {
        String oldmoney, xiaoyixulie, touzhi, miyaobanben, suanfabiaoshi, weisuijishu, zhongduantuojixuliehao;
        int strPsamSlot = OfflineSetting.psamSoltSignChip;
        String TerminalNum;

        String strCalMac1;
        String strTime;
        float num;
        try {
            //1.ICC选择1001开始
            Log.e(TAG, "1.1 ICC选择1001开始");
            String RQSelect1001ContentsCmd = "00A40000021001";
            Log.e(TAG, "1.2 ICC选择1001指令:" + RQSelect1001ContentsCmd);
            TransferChannel_res RESelect1001ContentsCmd = SDK_RSU.SendTransferChannel(1, "00A40000021001");
            String RESelect1001ContentsData = RESelect1001ContentsCmd.getData();
            if (!RESelect1001ContentsData.contains("9000")) {
                throw new NumberFormatException("ICC选择1001异常，返回值为:" + RESelect1001ContentsData);
            }
            Log.e(TAG, "1.3 ICC选择1001结束,返回值:" + RESelect1001ContentsData);
        } catch (Exception e) {
            throw new NumberFormatException("ICC选择1001文件," + e.getMessage());
        }


        try {
            //2.ICC读0015文件43字节
            Log.e(TAG, "2.1 ICC读0015文件开始");
            String RQSelect0015ContentsCmd = "00B095002B";
            Log.e(TAG, "2.2 ICC读0015文件指令:" + RQSelect0015ContentsCmd);
            TransferChannel_res RESelect0015ContentsCmd = SDK_RSU.SendTransferChannel(1, RQSelect0015ContentsCmd);
            String RESelect0015ContentsData = RESelect0015ContentsCmd.getData();
            if (!RESelect0015ContentsData.contains("9000")) {
                throw new NumberFormatException("ICC读0015文件异常，返回值为:" + RESelect0015ContentsData);
            }

            Log.e(TAG, "2.3 ICC读0015文件结束,返回值:" + RESelect0015ContentsData);
        } catch (Exception e) {
            throw new NumberFormatException("ICC读0015文件," + e.getMessage());
        }


        try {
            // 3、PSAM进3F00目录
            Log.e(TAG, "3.1 PSAM进3F00目录开始");
            String RQSelectContentsCmd = "00A40000023F00";
            Log.e(TAG, "3.2 PSAM进3F00指令:" + RQSelectContentsCmd);
            String RESelectContentsCmd = SDK_PSAM.PsamCos(strPsamSlot, RQSelectContentsCmd);
            if (!RESelectContentsCmd.contains("9000")) {
                throw new NumberFormatException("PSAM进3F00目录异常，返回值为:" + RESelectContentsCmd);
            }
            Log.e(TAG, "3.3 PSAM进3F00目录结束,应答为:" + RESelectContentsCmd);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM进3F00目录" + e.getMessage());

        }

        try {
            // 4、PSAM取终端号
            Log.e(TAG, "4.1 PSAM取终端号开始");
            String RQGetTerminalNumCmd = "00B0960006";
            Log.e(TAG, "4.2 PSAM取终端号指令:" + RQGetTerminalNumCmd);

            String REGetTerminalNumCmd = SDK_PSAM.PsamCos(strPsamSlot, RQGetTerminalNumCmd);
            if (!REGetTerminalNumCmd.contains("9000")) {
                throw new NumberFormatException("PSAM取终端号异常，返回值为:" + REGetTerminalNumCmd);
            }
            TerminalNum = REGetTerminalNumCmd.substring(0, REGetTerminalNumCmd.length() - 4);
            Log.e(TAG, "4.3 终端机编号为:" + TerminalNum);
            Log.e(TAG, "4.4 PSAM取终端号结束,应答为:" + REGetTerminalNumCmd);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM取终端号" + e.getMessage());

        }

        try {
            // 5、PSAM选DF01目录
            Log.e(TAG, "5.1 PSAM选DF01目录开始 ");
            String RQSelectDF01ContentsCmd = "00A4000002DF01";
            Log.e(TAG, "5.2 PSAM选DF01目录指令:" + RQSelectDF01ContentsCmd);

            String RESelectDF01ContentsCmd = SDK_PSAM.PsamCos(strPsamSlot, RQSelectDF01ContentsCmd);
            if (!RESelectDF01ContentsCmd.contains("9000")) {
                throw new NumberFormatException("PSAM选DF01目录异常，返回值为:" + RESelectDF01ContentsCmd);
            }
            Log.e(TAG, "5.3 PSAM选DF01目录结束,应答为:" + RESelectDF01ContentsCmd);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM选DF01目录" + e.getMessage());

        }
        try {
            //6.消费初始化
            Log.e(TAG, "6.1 消费初始化");
            num = Float.parseFloat(number) * 100;
            String strDeNum = HexUtil.LongToHexString((long) num, 4, 0);
            Log.e(TAG, "6.2 消费金额Hex:" + strDeNum);
            Log.e(TAG, "6.3 终端机编号:" + TerminalNum);

            String RQPayInitCmd = "805003020B" + "01" + strDeNum + TerminalNum;
            Log.e(TAG, "6.4 消费初始化指令:" + RQPayInitCmd);

            TransferChannel_res REPayInitCmd = SDK_RSU.SendTransferChannel(1, RQPayInitCmd);
            String REPayInitCmdData = REPayInitCmd.getData();
            if (!REPayInitCmdData.contains("9000")) {
                throw new NumberFormatException("消费初始化异常，返回值为:" + REPayInitCmdData);
            }


            oldmoney = REPayInitCmdData.substring(2, 10);
            Log.e(TAG, "4字节旧余额:" + oldmoney);
            xiaoyixulie = REPayInitCmdData.substring(10, 14);
            Log.e(TAG, "2字节电子钱包脱机交易序号:" + xiaoyixulie);
            touzhi = REPayInitCmdData.substring(14, 20);
            Log.e(TAG, "3字节透支限额:" + touzhi);
            miyaobanben = REPayInitCmdData.substring(20, 22);
            Log.e(TAG, "1字节密钥版本号:" + miyaobanben);

            suanfabiaoshi = REPayInitCmdData.substring(22, 24);
            Log.e(TAG, "1字节算法标识:" + suanfabiaoshi);
            weisuijishu = REPayInitCmdData.substring(24, 32);
            Log.e(TAG, "4字节伪随机数:" + weisuijishu);

            Log.e(TAG, "6.5消费初始化结束,返回值:" + REPayInitCmdData);
        } catch (Exception e) {
            throw new NumberFormatException("消费初始化," + e.getMessage());
        }


        try {
            //7.写0019文件
            Log.e(TAG, "7.1 写0019文件");

            String RQWrite0019Cmd = "80DCAAC82BAA290000000000000000000000000000000000000000000000000000000000000000000000000000000000";
            Log.e(TAG, "7.2 写0019文件指令:" + RQWrite0019Cmd);

            TransferChannel_res REWrite0019Cmd = SDK_RSU.SendTransferChannel(1, RQWrite0019Cmd);
            String REWrite0019CmdData = REWrite0019Cmd.getData();
            if (!REWrite0019CmdData.contains("9000")) {
                throw new NumberFormatException("写19文件异常，返回值为:" + REWrite0019CmdData);
            }

            Log.e(TAG, "7.3 写0019文件结束,返回值:" + REWrite0019CmdData);
        } catch (Exception e) {
            throw new NumberFormatException("写0019文件," + e.getMessage());
        }

        try {
            // 8、PSAM算MAC1
            Log.e(TAG, "8.1 PSAM算MAC1开始");
            strTime = "20140909120101";
            String strDeNum = HexUtil.LongToHexString((long) num, 4, 0);
            String RQGetMacCmd = "8070000024" + weisuijishu
                    + xiaoyixulie + strDeNum + "09"
                    + strTime + miyaobanben + suanfabiaoshi
                    + GetCardSerialNumber()
                    + GetIC0015().substring(0, 8)
                    + GetIC0015().substring(0, 8);
            Log.e(TAG, "8.2 PSAM算MAC1指令为:" + RQGetMacCmd);
            String REGetMacCmd = SDK_PSAM.PsamCos(strPsamSlot, RQGetMacCmd);
            if (!REGetMacCmd.contains("9000")) {
                throw new NumberFormatException("PSAM算MAC1异常，返回值为:" + REGetMacCmd);
            }
            zhongduantuojixuliehao = REGetMacCmd.substring(0, 8);
            strCalMac1 = REGetMacCmd.substring(8, 16);
            Log.e(TAG, "8.3 终端序列号为:" + strCalMac1);
            Log.e(TAG, "8.4 MAC1为:" + strCalMac1);
            Log.e(TAG, "8.5 PSAM算MAC1结束,应答为:" + REGetMacCmd);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM算MAC1" + e.getMessage());

        }


        try {
            //9.IC扣款 805401000F＋4 字节终端脱机交易序号＋7 字节交易日期时间＋4 字节MAC1
            Log.e(TAG, "9.1 IC扣款");
            Log.e(TAG, "9.2 4字节终端脱机交易序号:" + zhongduantuojixuliehao);
            Log.e(TAG, "9.3 交易时间为:" + strTime);
            Log.e(TAG, "9.4 4字节MAC1为:" + strCalMac1);
            String RQPayCmd = "805401000F" + zhongduantuojixuliehao + strTime + strCalMac1;

            Log.e(TAG, "9.5 IC扣款指令为:" + RQPayCmd);


            TransferChannel_res REPayCmd = SDK_RSU.SendTransferChannel(1, RQPayCmd);
            String REPayCmdData = REPayCmd.getData();
            if (!REPayCmdData.contains("9000")) {
                throw new NumberFormatException("IC扣款异常，返回值为:" + REPayCmdData);
            }

            Log.e(TAG, "9.6 IC扣款结束,返回值:" + REPayCmdData);
        } catch (Exception e) {
            throw new NumberFormatException("IC扣款," + e.getMessage());
        }


    }


}
